<?php
// +----------------------------------------------------------------------
// | APP版本
// +----------------------------------------------------------------------
// | Copyright (c) 2015-2024 http://www.yicmf.com, All rights reserved.
// +----------------------------------------------------------------------
// | Author: 微尘 <yicmf@qq.com>
// +----------------------------------------------------------------------
namespace app\event\app;

use app\common\event\Base;
use app\event\app\Rebate as RebateEvent;
use app\event\ucenter\Notice as NoticeEvent;
use app\event\ucenter\User as UserEvent;
use app\model\ucenter\User as UserModel;
use app\model\ucenter\UserMoneyLog as UserMoneyLogModel;
use app\model\ucenter\UserTask as UserTaskModel;
use app\model\app\PddOrder as PddOrderModel;
use app\model\app\PddGood as PddGoodModel;
use think\Exception;
use think\facade\Cache;
use think\facade\Db;
use think\helper\Str;
use yicmf\tools\HttpService;

class Pdd extends Base
{


    protected $client_id = 'ef4befb979244ce6b79226d242da1ebd';
    protected $client_secret = '8a27cee8fe779c54bfa0a18ec620648e24b611e8';
    protected $apiServerUrl = "https://gw-api.pinduoduo.com/api/router";

    protected $_user;
    protected $_pid = '41996579_297889039';


    public function pidGenerate()
    {

    }

    /**
     * 拼多多链接解析
     * @param $content
     * @param $user
     * @return void
     */
    public function parseContent($content, $user, $from)
    {
        try {
            if (!$user) {
                throw new Exception('请先登录');
            }
            $this->_user = $user;

            if (empty($user['pdd_pid'])) {
                // 先查询备案
                $authority = $this->authorityQuery($user['id']);
                if ($authority == 1) {
                    $user['pdd_pid'] = $this->_pid;
                    $user->save();
                }
            } else {
                $this->_pid = $user['pdd_pid'];
            }
            $search = $this->goodSearch($content);

            if (!isset($search['search_id']) || $search['total_count'] == 0) {
                throw new Exception('商品暂无返利');
            }
            $goods_sign = [];
            foreach ($search['goods_list'] as $index => $good) {
                $goods_sign[] = $good['goods_sign'];
            }
            $promotions = $this->promotionGenerate($goods_sign, $search['search_id']);

            $goods = [];
            foreach ($search['goods_list'] as $index => $good) {
                $good = array_merge($good, $promotions['goods_promotion_url_list'][$index]);
                $good['search_id'] = $search['search_id'];
                $good['keyword'] = $content;
                $good['user_id'] = $user['id'];
                foreach ($good as $index_item => $item) {
                    if (in_array($index_item, ['coupon_discount', 'coupon_min_order_amount', 'min_group_price', 'min_normal_price', 'order_amount', 'goods_price', 'share_amount', 'promotion_amount', 'platform_discount', 'subsidy_duo_amount_level', 'subsidy_duo_amount_ten_million', 'subsidy_amount'])) {
                        $good[$index_item] = $item / 100;
                    } elseif (in_array($index_item, ['activity_promotion_rate', 'predict_promotion_rate', 'promotion_rate', 'share_rate'])) {
                        $good[$index_item] = $item / 1000;
                    } elseif (in_array($index_item, ['has_coupon'])) {
                        $good[$index_item] = $item ? 1 : 0;
                    }
                }
                if ($from == 'link' && !$this->_user['pdd_pid'] || !$good['predict_promotion_rate']) {
                    $good['predict_promotion_rate'] = 0;
                    $good['check_time'] = time_format('1 hour');
                } else {
                    $good['check_time'] = null;
                    $good['check_ok_time'] = time_format('1 day');
                }
                $has = PddGoodModel::where('user_id', $user['id'])->where('keyword', $content)
                    ->where('goods_sign', $good['goods_sign'])
                    ->whereTime('create_time', '-24 hour')
                    ->find();
                // 查询近期
                $my_has = PddGoodModel::where('user_id', $user['id'])
                    ->where('goods_id', $good['goods_id'])
                    ->whereTime('update_time', '-24 hour')
                    ->find();
                if ($my_has) {
                    PddGoodModel::where('user_id', $user['id'])
                        ->where('goods_id', $good['goods_id'])
                        ->whereTime('update_time', '-24 hour')
                        ->update(['status' => 0]);
                }
                if ($has) {
                    if (!$has['check_time'] || strtotime($has['check_time']) <= time()) {
                        $has['check_time'] = time_format('1 hour');
                    }
                    $has['predict_promotion_rate'] = $good['predict_promotion_rate'];
                    $has['short_url'] = $good['short_url'];
                    $has['mobile_url'] = $good['mobile_url'];
                    $has['mobile_short_url'] = $good['mobile_short_url'];
                    $has['min_group_price'] = $good['min_group_price'];
                    $has['search_id'] = $search['search_id'];
                    $has->save();
                    $goods[] = RebateEvent::formatGood($has->toArray(), 'pdd');;
                } else {
                    $good = PddGoodModel::create($good);
                    $goods[] = RebateEvent::formatGood($good->toArray(), 'pdd');;
                }
            }
            $result['data'] = $goods;
            $result['data']['share'] = $goods[0];
            $result['tips'] = '您刚刚浏览过此商品，平台限制需要等待才有返利';
            $result['code'] = 0;
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            $result = ['code' => 1, 'message' => $e->getMessage()];
        }
        return $result;
    }

    /**
     * 拼多多链接解析
     * @param $content
     * @param $user
     * @return void
     */
    public function searchByKeyword($content, $user, $page = 1)
    {
        try {
            if (!$user) {
                throw new Exception('请先登录');
            }
            $this->_user = $user;

            if (empty($user['pdd_pid'])) {
                // 先查询备案
                $authority = $this->authorityQuery($user['id']);
                if ($authority == 1) {
                    $user['pdd_pid'] = $this->_pid;
                    $user->save();
                }
            } else {
                $this->_pid = $user['pdd_pid'];
            }
            $search = $this->goodSearch($content);
            if (!isset($search['search_id']) || $search['total_count'] == 0) {
                throw new Exception('当前关键词暂未搜索到相关信息');
            }
            foreach ($search['goods_list'] as $index => $good) {
                $good['search_id'] = $search['search_id'];
                $good['keyword'] = $content;
                $good['channel'] = 'pdd';
                $good['user_id'] = $user['id'];
                foreach ($good as $index_item => $item) {
                    if (in_array($index_item, ['coupon_discount', 'coupon_min_order_amount', 'min_group_price', 'min_normal_price', 'order_amount', 'goods_price', 'share_amount', 'promotion_amount', 'platform_discount', 'subsidy_duo_amount_level', 'subsidy_duo_amount_ten_million', 'subsidy_amount'])) {
                        $good[$index_item] = $item / 100;
                    } elseif (in_array($index_item, ['activity_promotion_rate', 'predict_promotion_rate', 'promotion_rate', 'share_rate'])) {
                        $good[$index_item] = $item / 1000;
                    } elseif (in_array($index_item, ['has_coupon'])) {
                        $good[$index_item] = $item ? 1 : 0;
                    }
                }

                $good['check_time'] = null;
                $good['check_ok_time'] = null;
                $has = PddGoodModel::where('user_id', $user['id'])->where('keyword', $content)
                    ->where('goods_sign', $good['goods_sign'])
                    ->find();
                // 查询近期
                if (!$has) {
                    $goods[] = PddGoodModel::create($good)->toArray();
                } else {
                    $goods[] = $has->toArray();
                }
            }
            $result['data'] = $goods;
            $result['code'] = 0;
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            $result = ['code' => 1, 'message' => $e->getMessage()];
        }
        return $result;
    }


    /**
     * 补单
     * @param $order
     * @param $user
     * @return array
     */
    public function supplement($order, $user)
    {
        try {
            if (!$order) {
                throw new Exception('订单异常');
            }
            $order['user_id'] = $user['id'];
            $order->save();
            $userTask = $this->_bindTask($order, $user);
            $this->_payFee($userTask);
            $result['code'] = 0;
        } catch (\Exception $e) {
            // 回滚事务
            $result = ['code' => 1, 'message' => $e->getMessage()];
        }
        return $result;
    }

    /**
     * 检查1小时等待
     * @param $time
     * @param $old_time
     * @return void
     * @throws Exception
     */
    public function checkOkPromotion()
    {
        try {
            $num = 0;
            $goods = PddGoodModel::whereTime('check_time', '<', 'now')->where('status', 1)->select();
            foreach ($goods as $index => $good) {
                $this->_user = UserModel::where('id', $good['user_id'])->find();
                $detail = $this->goodDetail($good['goods_sign'], $good['search_id']);
                if (isset($detail['goods_details']) && count($detail['goods_details']) == 1) {
                    $good['goods_gallery_urls'] = $detail['goods_details'][0]['goods_gallery_urls'];
                    $good['predict_promotion_rate'] = $detail['goods_details'][0]['predict_promotion_rate'] / 1000;
                } else {
                    continue;
                }
                if ($good['predict_promotion_rate'] > 0) {
                    $promotions = $this->promotionGenerate([$good['goods_sign']], $good['search_id']);
                    if (isset($promotions['goods_promotion_url_list']) && count($promotions['goods_promotion_url_list']) == 1) {
                        $promotion = $promotions['goods_promotion_url_list'][0];
                        $good['mobile_url'] = $promotion['mobile_url'];
                        $good['mobile_short_url'] = $promotion['mobile_short_url'];
                        $good['url'] = $promotion['url'];
                        $good['short_url'] = $promotion['short_url'];
                        $good['we_app_web_view_url'] = $promotion['we_app_web_view_url'];
                        $good['check_time'] = null;
                        $good['check_ok_time'] = time_format('1 day');
                        $good->save();
                        $param = [];
                        $param['type'] = 'rebate_pdd';
                        $param['relation_id'] = $good['id'];
                        $param['good'] = $good->toArray();
                        NoticeEvent::send($param, $this->_user);
                        $num++;
                    }
                } else {
                    // 不能返利，再次推迟5分钟
                    $good['check_time'] = time_format('5 minute');
                    $good->save();
                }
            }
            $result = ['code' => 0, 'data' => $num];
        } catch (\Exception $e) {
            // 回滚事务
            $result = ['code' => 1, 'message' => $e->getMessage()];
        }
        return $result;
    }


    /**
     * 根据更新状态
     * @param $time
     * @param $old_time
     * @return void
     * @throws Exception
     */
    public function getOrderByUpdate($time, $old_time = 1800)
    {

        try {
            $param['page_size'] = 100;
            $param['type'] = 'pdd.ddk.order.list.increment.get';
            $param['start_update_time'] = $time - $old_time;
            $param['end_update_time'] = $time;
            $res = $this->apiPost($param)['order_list_get_response'];
            if (!isset($res['order_list'])) {
                throw new Exception($res['message']);
            }
            foreach ($res['order_list'] as $trades) {
                $this->_sysnOrder($trades);
            }
            $result = ['code' => 0, 'data' => $res];
        } catch (\Exception $e) {
            // 回滚事务
            $result = ['code' => 1, 'message' => $e->getMessage()];
        }
        return $result;
    }

    /**
     * 根据更新状态
     * @param $time
     * @param $old_time
     * @return void
     * @throws Exception
     */
    public function statisticsQuery()
    {

        try {
            $param['period_type'] = 2;
            $param['statistics_type'] = 1;
            $param['type'] = 'pdd.ddk.statistics.data.query';
            $param['time'] = '2024-12-20';
            $res = $this->apiPost($param);

            $result = ['code' => 0, 'data' => $res];
        } catch (\Exception $e) {
            // 回滚事务
            $result = ['code' => 1, 'message' => $e->getMessage()];
        }
        return $result;
    }

    /**
     * 转链
     * @return void
     * @throws Exception
     */
    public function getUnitUrl($source_url)
    {

        $param['custom_parameters'] = '{"uid":"16006","sid":"22222"}';
        $param['type'] = 'pdd.ddk.goods.zs.unit.url.gen';
        $param['pid'] = $this->_pid;
        $param['source_url'] = $source_url;
        return $this->apiPost($param)['goods_zs_unit_generate_response'];

    }


    /**
     * 根据订单支付时间查询
     * @param $time
     * @param $old_time
     * @return mixed
     * @throws Exception
     */
    public function getOrder($time, $old_time = 1800)
    {

        $param['page_size'] = 100;
        $param['type'] = 'pdd.ddk.order.list.range.get';
        $param['start_time'] = time_format($time - $old_time, 'Y-m-d H:i:s');
        $param['end_time'] = time_format($time, 'Y-m-d H:i:s');
        $res = $this->apiPost($param)['order_list_get_response'];

        if (isset($res['order_list'])) {
            foreach ($res['order_list'] as $trades) {
                $this->_sysnOrder($trades);
            }
            return $res;
        } else {
            throw new Exception($res['message']);
        }

    }


    /**
     * 多多进宝推广链接生成
     * @param $goods_sign
     * @param $search_id
     * @return void
     * @throws Exception
     */
    protected function promotionGenerate($goods_sign, $search_id)
    {

        $param['custom_parameters'] = json_encode(['uid' => $this->_user['id'], 'sid' => $this->_user['username']]);
        if ($this->_user && !$this->_user['pdd_pid']) {
            $param['generate_authority_url'] = true;
        }
        $param['goods_sign_list'] = json_encode($goods_sign);
        $param['search_id'] = $search_id;
        $param['type'] = 'pdd.ddk.goods.promotion.url.generate';
        $param['p_id'] = $this->_pid;
        return $this->apiPost($param)['goods_promotion_url_generate_response'];
    }

    /**
     * 检查id是否备案
     * @param $uid
     * @return void
     * @throws Exception
     */
    protected function authorityQuery($uid)
    {

        $param['custom_parameters'] = json_encode(['uid' => $uid]);
        $param['type'] = 'pdd.ddk.member.authority.query';
        $param['pid'] = $this->_pid;
        $res = $this->apiPost($param)['authority_query_response'];
        return $res['bind'] == 1 ? 1 : 0;

    }


    /**
     * 产品搜索
     * @return void
     * @throws Exception
     */
    protected function goodSearch($keyword, $page = 1)
    {

        if ($this->_user && !empty($this->_user['pdd_pid'])) {
            $param['custom_parameters'] = json_encode(['uid' => $this->_user['id'], 'sid' => $this->_user['username']]);
        }
        $param['type'] = 'pdd.ddk.goods.search';
        $param['pid'] = $this->_pid;
        $param['page'] = $page;
        $param['page_size'] = 50;
        $param['keyword'] = $keyword;
        return $this->apiPost($param)['goods_search_response'];

    }

    /**
     * 产品详情
     * @return void
     * @throws Exception
     */
    protected function goodDetail($goods_sign, $search_id)
    {

        if ($this->_user && $this->_user['pdd_pid']) {
            $param['custom_parameters'] = json_encode(['uid' => $this->_user['id'], 'sid' => $this->_user['username']]);
        }
        $param['type'] = 'pdd.ddk.goods.detail';
        $param['pid'] = $this->_pid;
        $param['goods_sign'] = $goods_sign;
        $param['search_id'] = $search_id;
        return $this->apiPost($param)['goods_detail_response'];

    }


    private function _sysnOrder($trades)
    {
        $trade = [];
        foreach ($trades as $index_g => $item) {
            if (in_array($index_g, ['order_amount', 'goods_price', 'share_amount', 'promotion_amount', 'platform_discount', 'subsidy_duo_amount_level', 'subsidy_duo_amount_ten_million', 'subsidy_amount'])) {
                $trade[$index_g] = $item / 100;
            } elseif (in_array($index_g, ['activity_promotion_rate', 'promotion_rate', 'predict_promotion_rate', 'share_rate'])) {
                $good[$index_g] = $item / 1000;
            } else {
                $trade[Str::snake($index_g)] = $item;
            }
        }
        if ($trade['custom_parameters']) {
            $arr = json_decode($trade['custom_parameters'], true);
            $trade['custom_parameter_uid'] = $arr['uid'];
            $trade['user_id'] = $arr['uid'];
            $trade['custom_parameter_sid'] = $arr['sid'];
        } else {
            // $trade['user_id'] =16006;
        }
        if (!empty($trade['order_receive_time'])) {
            $trade['receive_time'] = time_format($trade['order_receive_time']);
            $trade['order_receive_time'] = time_format($trade['order_receive_time']);
        }
        $trade['create_time'] = time_format($trade['order_create_time']);
        $trade['pay_time'] = time_format($trade['order_pay_time']);

        $order = PddOrderModel::where('order_sn', $trade['order_sn'])->find();
        if (!$order) {
            $order = PddOrderModel::create($trade);
            if (!empty($order['user_id'])) {
                $user = UserModel::where('id', $order['user_id'])->find();
                if ($user) {
                    $userTask = $this->_bindTask($order, $user);
                    $this->_payFee($userTask);
                }
            }

        } else {
            // order_status 订单状态：0-已支付；1-已成团；2-确认收货；3-审核成功；4-审核失败（不可提现）；5-已经结算 ;10-已处罚
//            $order->allowField(['order_status', 'order_receive_time','order_settle_time','order_verify_time'])->save($trade);
            $order->save($trade);
            if ($order['user_id']) {
                $user = UserModel::where('id', $order['user_id'])->find();
                if ($user) {
                    $userTask = UserTaskModel::where('user_id', $user['id'])
                        ->where('task_id', 11)
                        ->where('task_type', 27)
                        ->where('relation_id', $order['id'])
                        ->find();
                    if ($userTask) {
                        $userTask['step'] = $order['order_status'];
                        $userTask['submit_info'] = $order->toArray();
                        $userTask->save();
                        $this->_payFee($userTask);
                    }
                }
            }
        }
    }


    private function _bindTask($order, $user)
    {
        // 新增任务
        $userTask['task_id'] = 11;
        $userTask['relation_id'] = $order['id'];
        $userTask['task_type'] = 27;
        $userTask['user_id'] = $user['id'];
        $userTask['agent_id'] = $user['agent_id'];
        $userTask['title'] = $order['goods_name'];
        $userTask['logo'] = $order['goods_thumbnail_url'];
        $userTask['money'] = $order['order_amount'];
        $userTask['commission'] = $order['promotion_amount'];
        $userTask['task_no'] = $order['order_sn'];
//        $userTask['end_time'] = time() + 30 * 86400;
        $userTask['step'] = $order['order_status'];
        $userTask['submit_info'] = $order->toArray();
        $userTask['status'] = 1;
        $userTask = UserTaskModel::create($userTask);
        if (!$userTask) {
            throw new Exception('系统故障');
        }
        return $userTask;
    }

    protected function _payFee($userTask)
    {

        //order_status 订单状态：0-已支付；1-已成团；2-确认收货；3-审核成功；4-审核失败（不可提现）；5-已经结算 ;10-已处罚

        if (in_array($userTask['step'], [4, 10])) {
            // 订单失效。
            $userTask['status'] = 3;
        } elseif (in_array($userTask['step'], [0])) {
            $userTask['status'] = 0;
        } elseif (in_array($userTask['step'], [1, 3])) {
            $userTask['status'] = 1;
        } elseif (in_array($userTask['step'], [2, 5])) {
            $userTask['status'] = 2;
            // 发放佣金
            $log = UserMoneyLogModel::where('user_id', $userTask['user_id'])->where('type', 39)
                ->where('order_id', $userTask['task_no'])
                ->where('channel', 'pdd')->find();

            $user = UserModel::where('id', $userTask['user_id'])->find();
            // 首单活动
            if (!$log) {
                $first = UserMoneyLogModel::where('user_id', $userTask['user_id'])->where('type', 39)
                    ->where('channel', 'pdd')->find();
                if (!$first) {
                    //拼多多首单
//                    UserEvent::money(1.8, $userTask['user_id'], '拼多多购物首单奖励', 88, $userTask['user_id']);
                    UserEvent::exhibitionIncome($user,1.8, '拼多多购物首单奖励', 39, $user['id'], $userTask['task_no'].'X1', 0, 'pdd', 11);

                }
            }

            if (!$log && !empty($userTask['commission']) && $userTask['commission'] > 0) {
                UserEvent::exhibitionIncome($user, $userTask['commission'], $userTask['title'], 39, $user['id'], $userTask['task_no'], 0, 'pdd', 11);
            }
        } else {
            $userTask['status'] = 4;
        }

        $userTask->save();
        if ($userTask['status'] == 3 || $userTask['status'] == 4) {
            // 失败订单，查询是否扣款
            $log = UserMoneyLogModel::where('user_id', $userTask['user_id'])->where('type', 39)
                ->where('order_id', $userTask['task_no'])
                ->where('channel', 'pdd')
                ->where('is_eversal', 0)
                ->find();
            if ($log) {
                $user = UserModel::where('id', $userTask['user_id'])->find();
                UserEvent::exhibitionIncomeBack($user, 39, '电商返利因退款或退货返佣取消', $user['id'], $userTask['task_no'], 'pdd', 11);
            }
        }
    }

    /**
     * 接口调用函数
     * @param $param
     * @return 接口返回信息
     */
    protected function apiPost($param)
    {

        $param['client_id'] = $this->client_id;
        $param['timestamp'] = time();
        $param['data_type'] = 'JSON';
        foreach ($param as $key => $val) {
            if (is_bool($val)) {
                $param[$key] = $val ? "true" : "false";
            }
        }
        $param['sign'] = $this->makeSign($param);
        $response = HttpService::get($this->apiServerUrl, $param);
        $content = $response['content'];
        if (isset($content['error_response'])) {
            throw new Exception($content['error_response']['sub_msg'], $content['error_response']['sub_code']);
        }
        return $response['content'];
    }

    /**
     * @param $request 请求的参数
     * @return 返回md5后的sign值
     */
    private function makeSign($params)
    {

        //签名步骤一：按字典序排序参数
        ksort($params);
        $string = $this->toUrlParams($params);
        //签名步骤二：在string首尾加上client_secret
        $string = $this->client_secret . $string . $this->client_secret;
        //签名步骤三：MD5加密
        $string = md5($string);
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    /**
     * 格式化参数格式化成url参数
     */
    private function toUrlParams($params)
    {
        $buff = "";
        foreach ($params as $k => $v) {
            if ($k != "sign" && $v !== "" && !is_array($v)) {
                $buff .= $k . $v;
            }
        }
        return $buff;
    }
}
